package com.hgh.nettydemo.javanio.javanioclient;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;

/**
 * @author: huguanghui
 * Created by huguanghui on 2018/6/18.
 * @Description:
 */
public class JavaNioClient {


    private Selector selector;
    SocketChannel socketChannel;
    private String hostIp = "127.0.0.1";


    private int hostListenningPort = 8888;


    public void createJavaNioClient(){
        try {
            // 获得一个Socket通道
            socketChannel = SocketChannel.open();
            // 设置通道为非阻塞
            socketChannel.configureBlocking(false);
            // 获得一个通道管理器
            this.selector = Selector.open();

            socketChannel.connect(new InetSocketAddress(hostIp, hostListenningPort));
            //将通道管理器和该通道绑定，并为该通道注册SelectionKey.OP_CONNECT事件。
            socketChannel.register(selector, SelectionKey.OP_CONNECT);

        } catch (Exception e) {

        }

        new ClientReadThread(selector);
    }


    public void sendMsg(String message) throws IOException {
        ByteBuffer writeBuffer = ByteBuffer.wrap(message.getBytes("UTF-8"));
        if (socketChannel.isConnectionPending()){
            socketChannel.finishConnect();
        }
        socketChannel.write(writeBuffer);
    }

    public class ClientReadThread implements Runnable{

        private Selector selector;

        public ClientReadThread(Selector selector){
            this.selector = selector;
            new Thread(this).start();
        }

        @Override
        public void run() {
            try {
                // 轮询访问selector
                while (true) {
                    selector.select();//如果队列有新的Channel加入，那么Selector.select()会被唤醒
                    // 获得selector中选中的项的迭代器
                    Iterator ite = this.selector.selectedKeys().iterator();
                    while (ite.hasNext()) {
                        SelectionKey key = (SelectionKey) ite.next();
                        // 删除已选的key,以防重复处理
                        ite.remove();
                        // 连接事件发生
                        if (key.isConnectable()) {
                            SocketChannel channel = (SocketChannel) key.channel();
                            // 如果正在连接，则完成连接
                            if (channel.isConnectionPending()) {
                                channel.finishConnect();
                            }
                            // 设置成非阻塞
                            channel.configureBlocking(false);

                            //在这里可以给服务端发送信息
                            channel.write(ByteBuffer.wrap(new String("hello world").getBytes()));
                            //在和服务端连接成功之后，为了可以接收到服务端的信息，需要给通道设置读的权限。
                            channel.register(this.selector, SelectionKey.OP_READ);
                        } else if (key.isReadable()) {
                            read(key);
                        }

                    }

                }

            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        public void read(SelectionKey key) throws IOException {

            // 服务器可读取消息:得到事件发生的Socket通道
            SocketChannel channel = (SocketChannel) key.channel();
            // 创建读取的缓冲区
            ByteBuffer buffer = ByteBuffer.allocate(10);
            channel.read(buffer);
            byte[] data = buffer.array();
            String content = new String(data);
             System.out.println(content);
        }

    }
}
